/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.aljfce.business.forecast.control;

import com.aljfce.business.entity.WeatherInformation;
import com.aljfce.business.entity.WeatherInformationPK;
import com.aljfce.business.mail.control.MailManager;
import com.aljfce.business.notification.control.NotificationManager;
import com.aljfce.business.utils.LoggerProducer;
import java.util.Date;
import java.util.List;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.transaction.UserTransaction;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.junit.InSequence;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.joda.time.DateTime;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;

/**
 *
 * @author jacopo
 */
@RunWith(Arquillian.class)
public class ForecasManagerIT {

    @Inject
    ForecastManager cut;

    @PersistenceContext
    EntityManager em;

    @Inject
    UserTransaction utx;

    @Deployment
    public static WebArchive createArchiveAndDeploy() {

        WebArchive wa = ShrinkWrap.create(WebArchive.class)
                .addClass(ForecastManager.class)
                .addClass(NotificationManager.class)
                .addClass(MailManager.class)
                .addPackages(true, NotificationManager.class.getPackage())
                .addPackages(true, MailManager.class.getPackage())
                .addPackage(WeatherInformation.class.getPackage())
                .addPackages(true, ForecastManager.class.getPackage())
                .addPackage(LoggerProducer.class.getPackage())
                .addAsResource("test-persistence.xml", "META-INF/persistence.xml")
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
        //System.out.println("ARCHIVE:\n" + wa.toString(true));
        return wa;
    }

    @Test
    @InSequence(1)
    public void forecastManagerShouldNotBeNull() {
        assertNotNull(cut);
    }

    @Test
    @InSequence(2)
    public void getForecastForExistingLocationShouldReturnValidObject() throws Exception {
        WeatherInformation wi = cut.getForecast("Milano", new Date());
        assertNotNull(wi);
        assertNotNull(wi.getConditionCode());
        assertNotNull(wi.getUrlImage());
        assertNotNull(wi.getDetails());

    }

    @Test
    @InSequence(3)
    public void updateForecastForExistingLocationShouldReturnValidObject() throws Exception {
        WeatherInformationPK wiPK = new WeatherInformationPK();
        wiPK.setDayTime(new DateTime().plusDays(2).toDate());
        wiPK.setLocation("Milano,it");
        WeatherInformation wi = new WeatherInformation(wiPK);
        WeatherInformation newWi = cut.updateForecast(wi);
        assertNotNull(newWi);
        assertNotNull(newWi.getConditionCode());
        assertNotNull(newWi.getUrlImage());
        assertNotNull(newWi.getDetails());
    }

    @Test
    @InSequence(4)
    public void deleteForecasShouldRemoveEntity() throws Exception {
        WeatherInformationPK wiPK = new WeatherInformationPK();
        wiPK.setDayTime(new DateTime().plusDays(2).toDate());
        wiPK.setLocation("Milano,it");
        WeatherInformation wi = new WeatherInformation(wiPK);
        wi.setConditionCode(800);
        wi.setDetails("Rain");
        wi.setUrlImage("http://www.test.com/icon.png");
        //Persist the entity to delete it
        utx.begin();
        em.persist(wi);
        utx.commit();
        //Remove the entity
        utx.begin();
        cut.deleteForecast(wi);
        utx.commit();
        WeatherInformation wiRemoved = em.find(WeatherInformation.class, wiPK);
        //Check that the entity do no exist in persistence context
        assertNull(wiRemoved);
    }

    @Test
    @InSequence(5)
    public void updateAllShouldUpdateAllEntity() throws Exception {
        int MAX = 10;
        WeatherInformation[] weaterInformations = new WeatherInformation[MAX];
        for (int i = 0; i < MAX; i++) {
            WeatherInformationPK wiPK = new WeatherInformationPK();
            wiPK.setDayTime(new DateTime().plusDays(i).toDate());
            wiPK.setLocation("Milano,it");
            WeatherInformation wi = new WeatherInformation(wiPK);
            wi.setConditionCode(800);
            wi.setDetails("NotValid");
            wi.setUrlImage("http://www.test.com/icon.png");
            utx.begin();
            em.merge(wi);
            utx.commit();
            weaterInformations[i] = wi;
        }
        cut.updateAll();

        TypedQuery<WeatherInformation> query = em.createNamedQuery("WeatherInformation.findAll", WeatherInformation.class);
        List<WeatherInformation> allWeatherInformation = query.getResultList();
        //Check that all the fields are updated
        for (int i = 0; i < MAX; i++) {
            assertNotEquals(allWeatherInformation.get(i).getDetails(), weaterInformations[i].getDetails());
        }

        //Cleanup
        utx.begin();
        for (WeatherInformation wi : allWeatherInformation) {
            //cut.deleteForecast(wi);
            em.remove(em.find(WeatherInformation.class, wi.getWeatherInformationPK()));
        }
        utx.commit();

    }

}
